import UIKit
//模块和源文件.模块是指Framework和app bundle.在Swfit中通过import 引入自己的工程。源文件是Swfit中的Swift file.就是编写Swift代码的文件。它通常属于一个模块。
//Swift提供三种访问级别
//Public：可以访问自己模块或应用中源文件的任何实体。别人也可以访问引入该模块中源文件的所有实体。
//Internal: 可以访问自己模块或应用中源文件的任何实体,但是别人不能访问该模块中源文件里的实体  这也是默认的级别
//Private: 只能在当前源文件中使用的实体。称为私有实体。使用Private级别，用作隐藏某些功能的实现细节。

public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}

private var somePublicVaraiable = 0
private let someInternalConstant = 0
private func somePrivateFunction() {}

//默认级别Internal
class InternalClass {} //隐式访问级别Internal
var internalConstant = 0 //隐式访问级别Internal

//类的访问级别也可以影响到类成员（属性，函数，初始化方法）。一个public类的所有成员访问级别默认为internal而不是public，如果你想要将某个成员申明为public，你必须用修复符明确的申明该成员为public.
public class aPublicClass {
    public var somePublicProperty = 0 //显示的public类成员
    var someInternalProperty = 0 //隐式的 internal 类成员
    private func somePrivateMethod() {} //显示的private类成员
}


class aInternalClass {  //隐式的internal类
    var someInternalProperty = 0 //隐式的internal类成员
    private func somePrivateMethod(){} //显示的private类成员
}

private class aPrivateClass {  //显示的private类
    var aPrivateProperty = 0 //隐式的private成员
    func somePrivateMethod() {} //隐式的private类成员
}

//元祖类型。访问级别是所有类型级别使用中最为严谨的。它遵循里面元祖中最低级的访问级别。


//函数类型。访问级别根据函数的参数类型访问级别，返回类型的访问级别得出。下面函数的返回值是元祖，一个参数是internal一个是private,因为元祖的访问基本是以最低的访问级别来确定，所以要显示的定义private 或者 fileprivate
fileprivate func someFunction() -> (a:SomeInternalClass , b:SomePrivateClass)
{
    return (SomeInternalClass(), SomePrivateClass())
}

// 枚举类型。 枚举中的成员的访问级别继承自枚举，不能为枚举中的成员指定访问级别

public enum CompassPoint {
    case North //public
    case South //public
}

private enum Direction {
    case East //private
    case West //private
}

//原始值和关联值。至少要高于枚举的访问级别

//嵌套类型 如果在private级别的类型中定义嵌套类型，那么嵌套类型默认自动拥有private级别。

//子类 不能高于父类的访问级别。
public class A {
    internal func someMethod(){}
}


internal class B : A {
    override public func someMethod(){
        super.someMethod()
    }
}

//常量，变量，属性和下标 不能拥有比他们的类型更高的级别。比如下面例子，编译报错。SomePrivateClass定义成Private,而默认情况不指定级别就是internal，高于了类型的级别是不允许的。
//var privateInstance = SomePrivateClass()

private var privateInstance = SomePrivateClass() //允许

//getter，setter访问级别继承于他们所属的成员
struct TrackString {
    private(set) var numberOfEdits = 0
    var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
}

//private (set) 意味着numberOfEdits只能在定义该结构体的源文件中被赋值。它的getter依然是默认的访问级别internal,但是setter的级别是private.这表明该属性只有在当前源文件是可读写，但是在源文件所属的模块它只读而已。
var stringToEdit = TrackString()
stringToEdit.value = "the string will be tracked"
stringToEdit.value += "this edit1"
stringToEdit.value += "so will edit2"
print("the number of edit is \(stringToEdit.numberOfEdits)")

//初始化。必须低于或等于它所属类的访问级别。默认初始化方法跟类访问级别相同
//结构体的默认成员初始化方法。如果结构体中任意存储属性的访问级别是private,那么它的默认成员初始化方法访问级别就是private.尽管如此，，结构体的初始化方法的访问级别依然是internal

//协议 每个必须要实现的函数都具有和该协议相同的访问级别。
//协议继承 如果你定义了一个协议，并且该协议继承了一个已知的协议，那么新协议拥有的访问级别最高也只和被继承的协议访问级别相同。
//协议的一致性。类可以采用比自身级别低的协议。采用协议后，类的访问级别就是协议的访问级别

//扩展 扩展成员应和原始类成员一致的访问级别。或者明确的申明扩展的访问级别
private extension Int {
    
}

//协议的扩展 如果扩展采用某个协议，那你就不能对该扩展的访问级别使用修饰符了。该扩展中实现的方法都会遵循该协议的访问级别

//泛型 泛型类型或函数的访问级别遵循泛型类型，函数本身、泛型类型参数三者中访问级别最低的级别。
//类型别名. 类型别名的级别低于或等于这个类型的访问级别

